<template>
  <div class="department-tree-container" @contextmenu.prevent="handleTreeContextMenu">
    <div class="tree-header">
      <span class="tree-title">部门组织</span>
      <div class="header-actions">
        <el-button
          type="primary"
          size="small"
          text
          @click="handleAddRootDepartment"
          title="添加根部门"
        >
          <el-icon><Plus /></el-icon>
        </el-button>
      </div>
    </div>
    
    <!-- 全部用户选项 -->
    <div 
      class="root-node" 
      :class="{ 'is-selected': !props.selectedDepartmentId }"
      @click="handleRootNodeClick"
    >
      <el-icon class="node-icon"><UserFilled /></el-icon>
      <span class="node-text">全部用户</span>
      <span v-if="totalUserCount > 0" class="user-count">({{ totalUserCount }})</span>
    </div>
    
    <el-tree
      ref="treeRef"
      v-loading="loading"
      :data="departmentTree"
      :props="treeProps"
      node-key="id"
      :expand-on-click-node="false"
      :highlight-current="true"
      :default-expand-all="false"
      :filter-node-method="filterNode"
      @node-click="handleNodeClick"
      @node-contextmenu="handleNodeContextMenu"
    >
      <template #default="{ node, data }">
        <div
          class="tree-node"
          :data-department-id="data.id"
          :draggable="true"
          @dragstart="handleDragStart($event, data)"
          @dragover.prevent="handleDragOver($event, data)"
          @drop="handleDrop($event, data)"
          @dragend="handleDragEnd"
        >
          <span class="node-label">
            <el-icon class="node-icon"><OfficeBuilding /></el-icon>
            <span class="node-text">{{ node.label }}</span>
            <span v-if="data.user_count > 0" class="user-count">({{ data.user_count }})</span>
          </span>
          <span v-if="hoveredNodeId === data.id" class="node-actions">
            <el-button
              type="primary"
              size="small"
              text
              @click.stop="handleAddChild(data)"
              title="添加子部门"
            >
              <el-icon><Plus /></el-icon>
            </el-button>
          </span>
        </div>
      </template>
    </el-tree>

    <!-- 右键菜单 -->
    <div
      v-if="contextMenuVisible"
      class="context-menu"
      :style="{ left: contextMenuPosition.x + 'px', top: contextMenuPosition.y + 'px' }"
      @click.stop
    >
      <div class="context-menu-item" @click="handleContextMenuAction('add-child')">
        <el-icon><Plus /></el-icon>
        <span>添加子部门</span>
      </div>
      <div class="context-menu-item" @click="handleContextMenuAction('edit')">
        <el-icon><Edit /></el-icon>
        <span>编辑</span>
      </div>
      <div class="context-menu-divider"></div>
      <div class="context-menu-item" @click="handleContextMenuAction('delete')">
        <el-icon><Delete /></el-icon>
        <span>删除</span>
      </div>
    </div>

    <!-- 部门对话框 -->
    <DepartmentDialog
      v-model:visible="dialogVisible"
      :department="currentDepartment"
      :parent-department="parentDepartment"
      @success="handleDialogSuccess"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, onUnmounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  Plus,
  Edit,
  Delete,
  OfficeBuilding,
  UserFilled
} from '@element-plus/icons-vue'
import { getDepartmentTree, deleteDepartment, moveDepartment } from '@/api/departments'
import type { Department } from '@/types/department'
import DepartmentDialog from './DepartmentDialog.vue'

interface Props {
  selectedDepartmentId?: string
  includeUsers?: boolean
  totalUserCount?: number
}

interface Emits {
  (e: 'node-click', department: Department | null): void
  (e: 'department-updated'): void
}

const props = withDefaults(defineProps<Props>(), {
  selectedDepartmentId: '',
  includeUsers: true,
  totalUserCount: 0
})

const emit = defineEmits<Emits>()

const treeRef = ref()
const loading = ref(false)
const departmentTree = ref<Department[]>([])
const hoveredNodeId = ref<string | null>(null)
const contextMenuVisible = ref(false)
const contextMenuPosition = ref({ x: 0, y: 0 })
const contextMenuData = ref<Department | null>(null)
const draggedNode = ref<Department | null>(null)
const dialogVisible = ref(false)
const currentDepartment = ref<Department | null>(null)
const parentDepartment = ref<Department | null>(null)

const treeProps = {
  label: 'name',
  children: 'children'
}

// 加载部门树
const loadDepartmentTree = async () => {
  loading.value = true
  try {
    const response = await getDepartmentTree({ include_users: props.includeUsers })
    // 处理API响应格式：response.data 是 axios 响应，response.data.data 是实际的 API 响应数据
    const apiResponse = response?.data as any
    if (apiResponse && typeof apiResponse === 'object' && 'success' in apiResponse) {
      // API 响应格式：{ success: true, data: [...] }
      if (apiResponse.success && apiResponse.data) {
        departmentTree.value = Array.isArray(apiResponse.data) ? apiResponse.data : []
      } else {
        departmentTree.value = []
      }
    } else if (Array.isArray(apiResponse)) {
      // 兼容直接返回数组的情况
      departmentTree.value = apiResponse
    } else if (Array.isArray(response?.data)) {
      // 兼容旧格式
      departmentTree.value = response.data
    } else {
      departmentTree.value = []
    }
  } catch (error: any) {
    console.error('加载部门树失败:', error)
    ElMessage.error(error?.message || '加载部门树失败')
    departmentTree.value = []
  } finally {
    loading.value = false
  }
}

// 根节点点击（全部用户）
const handleRootNodeClick = () => {
  emit('node-click', null)
  if (treeRef.value) {
    treeRef.value.setCurrentKey(null)
  }
}

// 节点点击
const handleNodeClick = (data: Department) => {
  emit('node-click', data)
  if (treeRef.value) {
    treeRef.value.setCurrentKey(data.id)
  }
}

// 设置当前选中的节点
const setCurrentKey = (key: string | null) => {
  if (treeRef.value) {
    treeRef.value.setCurrentKey(key)
  }
}

// 节点右键菜单
const handleNodeContextMenu = (event: MouseEvent, data: Department) => {
  contextMenuVisible.value = true
  contextMenuPosition.value = { x: event.clientX, y: event.clientY }
  contextMenuData.value = data
}

// 树空白区域右键
const handleTreeContextMenu = () => {
  contextMenuVisible.value = false
}

// 右键菜单操作
const handleContextMenuAction = async (action: string) => {
  contextMenuVisible.value = false
  if (!contextMenuData.value) return

  const data = contextMenuData.value

  switch (action) {
    case 'add-child':
      handleAddChild(data)
      break
    case 'edit':
      handleEdit(data)
      break
    case 'delete':
      await handleDelete(data)
      break
  }
}

// 添加根部门
const handleAddRootDepartment = () => {
  currentDepartment.value = null
  parentDepartment.value = null
  dialogVisible.value = true
}

// 添加子部门
const handleAddChild = (parent: Department) => {
  currentDepartment.value = null
  parentDepartment.value = parent
  dialogVisible.value = true
}

// 编辑部门
const handleEdit = (department: Department) => {
  currentDepartment.value = department
  parentDepartment.value = null
  dialogVisible.value = true
}

// 对话框成功回调
const handleDialogSuccess = async () => {
  await loadDepartmentTree()
  emit('department-updated')
  // 如果编辑的是当前选中的部门，保持选中状态
  if (currentDepartment.value && treeRef.value) {
    treeRef.value.setCurrentKey(currentDepartment.value.id)
  }
}

// 删除部门
const handleDelete = async (department: Department) => {
  try {
    await ElMessageBox.confirm(
      `确定要删除部门 "${department.name}" 吗？如果部门下有子部门或用户，将无法删除。`,
      '确认删除',
      {
        type: 'warning',
        confirmButtonText: '删除',
        cancelButtonText: '取消'
      }
    )

    await deleteDepartment(department.id)
    ElMessage.success('删除成功')
    await loadDepartmentTree()
    emit('department-updated')
  } catch (error: any) {
    if (error !== 'cancel') {
      console.error('删除部门失败:', error)
      ElMessage.error(error?.message || '删除部门失败')
    }
  }
}

// 拖拽开始
const handleDragStart = (event: DragEvent, data: Department) => {
  if (event.dataTransfer) {
    event.dataTransfer.effectAllowed = 'move'
    event.dataTransfer.setData('department-id', data.id)
  }
  draggedNode.value = data
}

// 拖拽悬停
const handleDragOver = (event: DragEvent, data: Department) => {
  event.preventDefault()
  if (event.dataTransfer) {
    event.dataTransfer.dropEffect = 'move'
  }
  const target = event.currentTarget as HTMLElement
  if (target && draggedNode.value && draggedNode.value.id !== data.id) {
    target.classList.add('drag-over')
  }
}

// 拖拽放置
const handleDrop = async (event: DragEvent, targetDepartment: Department) => {
  event.preventDefault()
  const target = event.currentTarget as HTMLElement
  if (target) {
    target.classList.remove('drag-over')
  }

  if (!draggedNode.value || draggedNode.value.id === targetDepartment.id) {
    return
  }

  // 检查是否会造成循环引用
  if (isDescendant(targetDepartment, draggedNode.value)) {
    ElMessage.warning('不能将部门移动到其子部门下')
    return
  }

  try {
    await moveDepartment(draggedNode.value.id, {
      new_parent_id: targetDepartment.id
    })
    ElMessage.success('移动成功')
    await loadDepartmentTree()
    emit('department-updated')
  } catch (error: any) {
    console.error('移动部门失败:', error)
    ElMessage.error(error?.message || '移动部门失败')
  }
}

// 拖拽结束
const handleDragEnd = () => {
  // 清除所有拖拽样式
  document.querySelectorAll('.drag-over').forEach(el => {
    el.classList.remove('drag-over')
  })
  draggedNode.value = null
}

// 检查是否是子节点
const isDescendant = (ancestor: Department, descendant: Department): boolean => {
  if (!ancestor.children || ancestor.children.length === 0) {
    return false
  }
  for (const child of ancestor.children) {
    if (child.id === descendant.id) {
      return true
    }
    if (isDescendant(child, descendant)) {
      return true
    }
  }
  return false
}

// 过滤节点
const filterNode = (value: string, data: any) => {
  if (!value) return true
  const dept = data as Department
  return dept.name?.toLowerCase().includes(value.toLowerCase()) ?? false
}

// 过滤树
const filter = (value: string) => {
  if (treeRef.value) {
    treeRef.value.filter(value)
  }
}

// 点击外部关闭右键菜单
const handleClickOutside = () => {
  contextMenuVisible.value = false
}

// 监听选中部门变化
watch(() => props.selectedDepartmentId, (newId) => {
  if (treeRef.value && newId) {
    treeRef.value.setCurrentKey(newId)
  }
})

onMounted(() => {
  loadDepartmentTree()
  document.addEventListener('click', handleClickOutside)
})

onUnmounted(() => {
  document.removeEventListener('click', handleClickOutside)
})

// 暴露方法
defineExpose({
  loadDepartmentTree,
  filter,
  setCurrentKey,
  departmentTree
})
</script>

<style scoped lang="scss">
.department-tree-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: white;
  border-radius: 4px;
  overflow: hidden;
}

.tree-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid #e4e7ed;
  background: #fafafa;

  .tree-title {
    font-weight: 600;
    font-size: 14px;
    color: #303133;
  }

  .header-actions {
    display: flex;
    align-items: center;
    gap: 4px;
  }
}

.root-node {
  display: flex;
  align-items: center;
  padding: 8px 16px;
  cursor: pointer;
  transition: background-color 0.2s;
  border-bottom: 1px solid #f0f0f0;
  
  &:hover {
    background-color: #f5f7fa;
  }
  
  &.is-selected {
    background-color: #ecf5ff;
    color: #409eff;
    font-weight: 500;
  }
  
  .node-icon {
    margin-right: 8px;
    font-size: 16px;
  }
  
  .node-text {
    flex: 1;
    font-size: 14px;
  }
  
  .user-count {
    color: #909399;
    font-size: 12px;
    margin-left: 4px;
  }
}

:deep(.el-tree) {
  flex: 1;
  overflow-y: auto;
  padding: 8px;
  background: white;
}

.tree-node {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex: 1;
  padding: 4px 0;
  cursor: pointer;
  user-select: none;

  &:hover {
    .node-actions {
      display: flex;
    }
  }

  &.drag-over {
    background-color: #e6f7ff;
    border: 1px dashed #1890ff;
  }

  .node-label {
    display: flex;
    align-items: center;
    flex: 1;
    min-width: 0;

    .node-icon {
      margin-right: 6px;
      color: #909399;
      font-size: 16px;
    }

    .node-text {
      flex: 1;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .user-count {
      margin-left: 6px;
      color: #909399;
      font-size: 12px;
    }
  }

  .node-actions {
    display: none;
    align-items: center;
    gap: 4px;
    margin-left: 8px;
  }
}

.context-menu {
  position: fixed;
  background: white;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  z-index: 3000;
  min-width: 160px;
  padding: 4px 0;

  .context-menu-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    cursor: pointer;
    font-size: 14px;
    color: #606266;

    &:hover {
      background-color: #f5f7fa;
      color: #409eff;
    }

    .el-icon {
      font-size: 16px;
    }
  }

  .context-menu-divider {
    height: 1px;
    background-color: #e4e7ed;
    margin: 4px 0;
  }
}
</style>

